/**
 * =====================================================================================
 *
 *      @file:  cache.c
 *
 *    	@brief:  对openPlant数据进行缓存
 *
 *      @version:  1.0
 *      Created:  2010年04月12日 15时05分56秒
 *      Revision:  none
 *      Compiler:  gcc -Wall -Wextra cache.c
 *
 *      @author:  easyeagel (LiuGuangBao), easyeagel@gmx.com
 *      Company:  简单C++ - www.easycpp.org
 *
 * =====================================================================================
 */

#include<assert.h>
#include<stdio.h>
#include"opmap.hpp"
#include"base.hpp"
#include"cache.hpp"

static void point_copy(void* dest, const void* src);
static int point_compare(const void* l, const void* r);
static void point_destroy(void* v);
static void node_cache_copy(void* dest, const void* src);
static int node_cache_compare(const void* l, const void* r);
static void node_cache_destroy(void* v);
static void plant_cache_copy(void* dest, const void* src);
static int plant_cache_compare(const void* l, const void* r);
static void plant_cache_destroy(void* v);

/* ========================================================== */
/* 调试用工具 */

void srlt_node_print(OPnode_cache_t* node)
{
	size_t point_num=node->point->index;
	for(size_t i=0; i < point_num; ++i)
	{
		OPpoint_t* point=(OPpoint_t*)vct_index(node->point, i);
		printf("%s.%s\n", node->info.info.name, point->info.name);
	}
}

void srlt_plant_print(OPplant_cache_t* plant)
{
	size_t node_num=plant->node->index;
	for(size_t i=0; i < node_num; ++i)
	{
		OPnode_cache_t* node=(OPnode_cache_t*)vct_index(plant->node, i);
		printf("%s.%s\n", plant->info.name, node->info.info.name);
		srlt_node_print(node);
	}
}

void srlt_cache_print(cache_t* cac)
{
	size_t plant_num=cac->plant->index;
	for(size_t i=0; i<plant_num; ++i)
	{/* 打印一个plant */
		OPplant_cache_t* plant=(OPplant_cache_t*)vct_index(cac->plant, i);
		printf("plant:%s\n", plant->info.name);
		srlt_plant_print(plant);
	}
}

/* =========================================================== */
/* 基本操作函数 */
int srlt_cache_init(cache_t* cac) /* 只分配当前层的空间 */
{
	/* 分配内存，在外面 */
	size_t cache_capacity = MinitSize;
	/* 指向OPplant_cache_t结构 */
	vector_t* plant_list=vct_create(sizeof(OPplant_cache_t), cache_capacity);
	assert(plant_list);

	vct_fun_compare(plant_list, plant_cache_compare);
	vct_fun_copy(plant_list, plant_cache_copy);
	vct_fun_destroy(plant_list, plant_cache_destroy);

#if 0
	/* 为每一个plant调用srlt_plant_cache_init */
	OPplant_cache_t* plant;
	size_t i=-1;
	while((plant=(OPplant_cache_t*)vct_index(plant_list, ++i)))
	{
		srlt_plant_cache_init(plant);
	}
#endif

	cac->plant=plant_list;

	return RLT_yes;
};

int srlt_plant_cache_init(OPplant_cache_t* plant, size_t num)
{
	/* 指向OPnode_cache_t结构 */
	vector_t* node_list=vct_create(sizeof(OPnode_cache_t), num);
	assert(node_list);

	vct_fun_compare(node_list, node_cache_compare);
	vct_fun_copy(node_list, node_cache_copy);
	vct_fun_destroy(node_list, node_cache_destroy);
	plant->node=node_list;

#if 0
	OPnode_cache_t* node;
	size_t i=-1;
	while((node=(OPnode_cache_t*)vct_index(node_list, ++i)))
	{
		srlt_node_cache_init(node);
	}
#endif

	return RLT_yes;
}

int srlt_node_cache_init(OPnode_cache_t* node, size_t num)
{
	/* 指向OPpoint_t结构 */
	vector_t* point_list=vct_create(sizeof(OPpoint_t), num);
	assert(point_list);

	vct_fun_compare(point_list, point_compare);
	vct_fun_copy(point_list, point_copy);
	vct_fun_destroy(point_list, point_destroy);

	node->point=point_list;

	return RLT_yes;
}

int srlt_cache_load(cache_t* cac, const char** ps)
{
	/* 为每一个工厂加载缓存 */
	while(*ps)
	{
		OPplant_cache_t plant;
		time_t ctime=time(NULL);
		plant.info.name=str_dup(*ps);
		plant.info.last_update=ctime;
		plant.info.parent=cac;
		if(RLT_yes==srlt_plant_cache_load(&plant))
		{
			plant.last_update=ctime;
			vct_pushback(cac->plant, (void*)(&plant));
		}

		++ps;
	}

	return RLT_yes;
}

int srlt_plant_cache_load(OPplant_cache_t* plant)
{
	OPRESHANDLE result;
	int ret=op_select_node(plant->info.name, &result);
	if(0!=ret)
	{
		return RLT_no;
	}

	NodeInfo info;
	size_t num=op_num_rows(result);
	srlt_plant_cache_init(plant, num);
	while(0!=op_fetch_node_info(result, &info))
	{
		OPnode_cache_t node;
		time_t ctime=time(NULL);
		node.info.info=info;
		node.info.last_update=ctime;
		node.info.parent=plant;
		if(RLT_yes==srlt_node_cache_load(&node))
		{
			node.last_update=ctime;
			vct_pushback(plant->node, (void*)(&node));
		}
	}

	return RLT_yes;
}

int srlt_node_cache_load(OPnode_cache_t* node)
{
	char tname[RLT_max_path_length];
	strcpy(tname, node->info.parent->info.name);
	strcat(tname, ".");
	strcat(tname, node->info.info.name);

	OPRESHANDLE result;
	int ret=op_select_point(tname, &result);
	if(0!=ret)
	{
		return RLT_no;
	}

	size_t num=op_num_rows(result);
	srlt_node_cache_init(node, num);
	PointInfo info;
	while(0!=op_fetch_point_info(result, &info))
	{
		OPpoint_t point;
		time_t ctime=time(NULL);
		point.info=info;
		point.last_update=ctime;
		point.parent=node;
		vct_pushback(node->point, &point);
	}

	return RLT_yes;
}

/* ============================================================== */
/* 回调函数,这里的复制函数都是移动复制的，也就是浅层复制 */
/* 而比较都是以名字进行的比较 */
static void point_copy(void* dest, const void* src)
{
	memcpy(dest, src, sizeof(OPpoint_t));
}

static int point_compare(const void* l, const void* r)
{
	OPpoint_t* pl=(OPpoint_t*)l;
	OPpoint_t* pr=(OPpoint_t*)r;

	return strcmp(pl->info.name, pr->info.name);
}

static void point_destroy(void* v)
{
	v=0;
}

static void node_cache_copy(void* dest, const void* src)
{
	memcpy(dest, src, sizeof(OPnode_cache_t));
}

static int node_cache_compare(const void* l, const void* r)
{
	OPnode_cache_t* pl=(OPnode_cache_t*)l;
	OPnode_cache_t* pr=(OPnode_cache_t*)r;

	return strcmp(pl->info.info.name, pr->info.info.name);
}

static void node_cache_destroy(void* v)
{
	OPnode_cache_t* pv=(OPnode_cache_t*)v;
	vct_free(pv->point);
}

static void plant_cache_copy(void* dest, const void* src)
{
	memcpy(dest, src, sizeof(OPplant_cache_t));
}

static int plant_cache_compare(const void* l, const void* r)
{
	OPplant_cache_t* pl=(OPplant_cache_t*)l;
	OPplant_cache_t* pr=(OPplant_cache_t*)r;

	return strcmp(pl->info.name, pr->info.name);
}

static void plant_cache_destroy(void* v)
{
	OPplant_cache_t* pv=(OPplant_cache_t*)v;
	vct_free(pv->node);
}

